#include "cmdpacketrecv.h"

void RegisterCmdPackClass(){
    static bool haveRegister = false;
    if(haveRegister)return;
    qRegisterMetaType<wtlogin_login>();
    qRegisterMetaType<StatSvc_register>();
    qRegisterMetaType<friendlist_GetTroopListReqV2>();
    qRegisterMetaType<MessageSvc_PbSendMsg>();
    qRegisterMetaType<OnlinePush_PbPushGroupMsg>();
    qRegisterMetaType<MessageSvc_PushNotify>();
    qRegisterMetaType<OnlinePush_ReqPush>();
    qRegisterMetaType<friendlist_getFriendGroupList>();
    qRegisterMetaType<MessageSvc_PbGetMsg>();
    qRegisterMetaType<MessageSvc_PushForceOffline>();
    haveRegister = true;
}

void wtlogin_login::unpack()
{
    //then we can call read method
    skipBytes(2);// subCommand
    readByte(type);
    skipBytes(2);
    readTLVS(tlvs);

    switch (type) {
    case 0:{
        loginResponse=LoginResponse::LoginSuccess;
        if(tlvs.contains(0x161))tlvSolver0x161.setData(tlvs[0x161]).unpack();
        if(tlvs.contains(0x119))tlvSolver0x119.setData(tlvs[0x119]).unpack();
        //TODO:use reflection TLVSolvers
    }break;
    case 15:case 1:{
        loginResponse=LoginResponse::ErrorMessage;
    }break;
    case 2:{
        loginResponse=LoginResponse::SolveLoginCaptcha;
        qDebug()<<loginResponse;
    }break;
    case -96:{
        loginResponse=LoginResponse::UnsafeDeviceLogin;
        deviceLockUrl = tlvs[0x204];
    }break;
    case 204:{
        loginResponse=LoginResponse::SMSVerifyNeeded;
        qDebug()<<loginResponse;
    }break;
    default:abort();//unknown ???
    }
}

CmdPacketRecv & CmdPacketRecv::setData(const QByteArray &data)
{
    DataReader::setData(data);
    return *this;
}

void StatSvc_register::unpack()
{
    //TODO UNIMPLEMENT
}

void friendlist_GetTroopListReqV2::unpack()
{
    QByteArray data;readAll(data);
    groupData = unpackUniResp(data);
}

void MessageSvc_PbSendMsg::unpack()
{
    QByteArray data;readAll(data);
    qqprotobuf::MsgSvc::PbSendMsgResp resp;
    resp.ParseFromString(data.toStdString());
    result = resp.result();
}

void OnlinePush_PbPushGroupMsg::unpack()
{
    QByteArray data;readAll(data);
    pbPushMsg.ParseFromString(data.toStdString());
}

void OnlinePush_ReqPush::unpack()
{
    QByteArray data;readAll(data);
    QByteArray tmp = unpackUniResp(data,"req",true).toMap()["req"].toMap()["OnlinePushPack.SvcReqPushMsg"].toByteArray();
    JceReader reader(tmp);
    reader.setServerEncoding(false);
    QVariant ret = QVariantMap();
    reader.parseObj(ret);//unpack as respacket
    auto vMsgInfos = ret.toMap()["0"].toMap()["2"].toList();
    foreach (auto item, vMsgInfos) {
        auto msgInfo = item.toMap();
        qDebug()<<msgInfo["2"].toInt()<<msgInfo["6"].toString();
    }
}

void MessageSvc_PushNotify::unpack()
{
    /*
    skipBytes(4);//TODO SOMETIME WRONG
    QByteArray data;readAll(data);
    JceReader reader(data);
    reader.setServerEncoding(false);
    QVariant ret = QVariantMap();
    reader.parseObj(ret);//unpack as respacket
    QVariant tmp = QVariantMap();
    reader.setData(ret.toMap()["7"].toByteArray()).parseObj(tmp);
    data = tmp.toMap()["0"].toMap()["req_PushNotify"].toMap()["PushNotifyPack.RequestPushNotify"].toByteArray();
    QVariant tmp2 = QVariantMap();
    reader.setData(data).parseObj(tmp2);
    qDebug()<<"fuk";//@SerialId(9) val stMsgInfo: MsgInfo?,
    */
    //fuck the shit package.
    //it have shit data
}

void friendlist_getFriendGroupList::unpack()
{
    QByteArray data;readAll(data);
    friendList = unpackUniResp(data);
}

QVariant unpackUniResp(const QByteArray &data, QString key,bool special)
{
    JceReader reader(data);
    reader.setServerEncoding(false);
    QVariant responsePacket = QVariantMap();
    reader.parseObj(responsePacket);//unpack as respacket
    QVariant repObj = QVariantMap();
    reader.setData(JceReader::convertQVMap(responsePacket)["7"].toByteArray()).parseObj(repObj);//unpack sbuffer as a object
    auto tmp = JceReader::convertQVMap(repObj)["0"].toMap();
    if(special)return tmp;
    QVariant ret = QVariantMap();
    reader.setData(tmp[key == ""?tmp.keys()[0]:key].toByteArray()).parseObj(ret);//unpack the target object
    //WARN THIS IS MAYBE MORE THAN ONE OBJECT
    //then unpack if the map have the only elem
    //it maybe a struct single
    if(ret.toMap().keys().size() == 1)ret = ret.toMap()[ret.toMap().keys()[0]];
    return ret;
}

void MessageSvc_PbGetMsg::unpack()
{
    QByteArray data;readAll(data);
    resp.ParseFromString(data.toStdString());
}

void MessageSvc_PushForceOffline::unpack()
{

}
